﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Aga.GestionDeArchivos.Web.Helpers;
using Aga.GestionDeArchivos.Services;
using Aga.GestionDeArchivos.Web.Models.Estanterias;
using AutoMapper;
using Aga.GestionDeArchivos.Domain.Entities;

namespace Aga.GestionDeArchivos.Web.Controllers
{
    public class EstanteriasController : ControllerBase
    {
        private const int PageSize = 10;

        public EstanteriasController()
        {
            ViewBag.Menu = MenuKey.Admin;
        }

        [CustomAuthorize(Actions = Aga.GestionDeArchivos.Services.Actions.ViewEstanterias)]
        public ActionResult Index(int? index, int? d, int? e)
        {
            d = d ?? 0;
            e = e ?? 0;

            EstanteriaService estanteriaService = new EstanteriaService();
            DepositoService depositoService = new DepositoService();

            var depositos = depositoService.GetAll();

            List<SelectListItem> filtroDepositos = GetFilter(d,
                depositos,
                dep => new SelectListItem { Text = String.Format("({0}) {1}", dep.Numero, dep.Nombre), Value = dep.Numero.ToString(), Selected = dep.Numero.Equals(d) });

            var estanterias = estanteriaService.GetAll();

            // Filtro la estantería
            if (d.HasValue && d > 0)
                estanterias = estanterias.Where(es => es.Deposito.Numero == d);

            List<SelectListItem> filtroEstanterias = GetFilter(e,
                estanterias.OrderBy(es => es.Numero).Select(es => es.Numero).Distinct().ToList(),
                num => new SelectListItem { Text = num.ToString(), Value = num.ToString(), Selected = num == e });

            if (e.HasValue && e > 0)
                estanterias = estanterias.Where(es => es.Numero == e);

            IndexModel model = new IndexModel
            {
                Estanterias = estanteriaService.GetPage(estanterias, index ?? 0, PageSize),
                EstanteriaId = e ?? 0,
                DepositoId = d ?? 0,
                FiltroEstanterias = filtroEstanterias,
                FiltroDepositos = filtroDepositos
            };

            return View(model);
        }

        private List<SelectListItem> GetFilter<T>(int? number, IEnumerable<T> values, Func<T, SelectListItem> selector, bool filtroTodas = true)
        {

            List<SelectListItem> items = new List<SelectListItem>();
            
            if (filtroTodas)
                items.Add(new SelectListItem { Text = "-", Value = "0", Selected = (!number.HasValue || number == 0) });
            
            foreach (var val in values)
            {
                items.Add(selector(val));
            }

            return items;
        }

        [CustomAuthorize(Actions = Aga.GestionDeArchivos.Services.Actions.CreateEstanterias)]
        public ActionResult Create()
        {
            DepositoService depositos = new DepositoService();
            EstanteriaService estanterias = new EstanteriaService();

            CreateModel model = new CreateModel()
            {
                Sectores = 1
            };

            model.Numero = estanterias.GetNextNumber();

            model.Depositos = new SelectList(depositos.GetAll(), "Id", "Nombre");

            return View(model);
        }

        [HttpPost]
        [CustomAuthorize(Actions = Aga.GestionDeArchivos.Services.Actions.CreateEstanterias)]
        public ActionResult Create(CreateModel model)
        {
            try
            {
                EstanteriaService estanterias = new EstanteriaService();
                DepositoService depositos = new DepositoService();

                if (ModelState.IsValid)
                {

                    var deposito = depositos.GetById(model.DepositoId);
                    int numero = estanterias.GetNextNumber();

                    for (int sector = 1; sector <= model.Sectores; sector++)
                    {
                        Estanteria estanteria = new Estanteria
                        {
                            Deposito = deposito,
                            Numero = numero,
                            Sector = sector,
                            Horizontal = model.Horizontal,
                            Vertical = model.Vertical,
                            Fondo = model.Fondo
                        };

                        estanterias.Save(estanteria);
                    }

                    return RedirectToAction("Index", new { index = 0, e = numero });
                }
                else
                {

                    model.Depositos = new SelectList(depositos.GetAll(), "Id", "Nombre", model.DepositoId);

                    model.Numero = estanterias.GetNextNumber();

                    return View(model);
                }
            }
            catch (Exception ex)
            {
                return ShowError(ex);
            }
        }

        [CustomAuthorize(Actions = Aga.GestionDeArchivos.Services.Actions.EditEstanterias)]
        public ActionResult Edit(int id)
        {
            EstanteriaService service = new EstanteriaService();
            DepositoService depositos = new DepositoService();

            Estanteria estanteria = service.GetById(id);

            Mapper.CreateMap<Estanteria, EditModel>();

            var model = Mapper.Map<Estanteria, EditModel>(estanteria);

            model.Deposito = depositos.GetById(estanteria.Deposito.Id).Nombre;

            return View(model);
        }

        [HttpPost]
        [CustomAuthorize(Actions = Aga.GestionDeArchivos.Services.Actions.EditEstanterias)]
        public ActionResult Edit(EditModel model)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    EstanteriaService service = new EstanteriaService();

                    Estanteria estanteria = service.GetById(model.Id);

                    estanteria.Horizontal = model.Horizontal;
                    estanteria.Vertical = model.Vertical;
                    estanteria.Fondo = model.Fondo;

                    service.Save(estanteria);

                    return RedirectToAction("Index");
                }
                else
                {
                    DepositoService depositos = new DepositoService();

                    model.Deposito = depositos.GetById(model.DepositoId).Nombre;

                    return View(model);
                }
            }
            catch (Exception ex)
            {
                return ShowError(ex);
            }
        }

        [CustomAuthorize(Actions = Aga.GestionDeArchivos.Services.Actions.DeleteEstanterias)]
        public ActionResult Delete(int id)
        {
            EstanteriaService service = new EstanteriaService();

            Estanteria estanteria = service.GetById(id);

            DeleteModel model = new DeleteModel
            {
                Id = estanteria.Id,
                Numero = estanteria.Numero,
                Sector = estanteria.Sector
            };

            return View(model);
        }

        [HttpPost]
        [CustomAuthorize(Actions = Aga.GestionDeArchivos.Services.Actions.DeleteEstanterias)]
        public ActionResult Delete(DeleteModel model)
        {
            try
            {
                EstanteriaService service = new EstanteriaService();

                service.Delete(model.Id);

                return RedirectToAction("Index");
            }
            catch (Exception ex)
            {
                return ShowError(ex);
            }
        }

        [CustomAuthorize(Actions = Aga.GestionDeArchivos.Services.Actions.EditEstanterias)]
        public ActionResult AgregarSector(int id)
        {
            EstanteriaService service = new EstanteriaService();
            DepositoService depositos = new DepositoService();

            Estanteria estanteria = service.GetById(id);

            int proximoSector = service.GetAll()
                                       .Where(e => e.Numero == estanteria.Numero)
                                       .Max(e => e.Sector) + 1;

            Mapper.CreateMap<Estanteria, EditModel>();

            var model = Mapper.Map<Estanteria, EditModel>(estanteria);

            model.Sector = proximoSector;

            model.Deposito = depositos.GetById(estanteria.Deposito.Id).Nombre;

            return View(model);
        }

        [HttpPost]
        [CustomAuthorize(Actions = Aga.GestionDeArchivos.Services.Actions.CreateEstanterias)]
        public ActionResult AgregarSector(EditModel model)
        {
            try
            {
                EstanteriaService estanterias = new EstanteriaService();
                DepositoService depositos = new DepositoService();

                if (ModelState.IsValid)
                {

                    var deposito = depositos.GetById(model.DepositoId);

                    Estanteria estanteria = new Estanteria
                    {
                        Deposito = deposito,
                        Numero = model.Numero,
                        Sector = model.Sector,
                        Horizontal = model.Horizontal,
                        Vertical = model.Vertical,
                        Fondo = model.Fondo
                    };

                    estanterias.Save(estanteria);

                    return RedirectToAction("Index", new { index = 0, e = model.Numero });
                }
                else
                {
                    model.Deposito = depositos.GetById(model.DepositoId).Nombre;

                    model.Numero = estanterias.GetNextNumber();

                    return View(model);
                }
            }
            catch (Exception ex)
            {
                return ShowError(ex);
            }
        }

        [CustomAuthorize(Actions = Aga.GestionDeArchivos.Services.Actions.ImprimirEtiquetasUbicaciones)]
        public ActionResult ImprimirEtiquetas()
        {
            EstanteriaService service = new EstanteriaService();

            List<int> estanterias = service.GetAllNumbers();

            List<SelectListItem> filtro = GetFilter(0,
                estanterias.Select(e => e).Distinct(),
                num => new SelectListItem { Text = num.ToString(), Value = num.ToString(), Selected = num.Equals(0) });

            EtiquetasModel model = new EtiquetasModel
            {
                EstanteriaId = 0,
                Estanterias = filtro,
                SectorDesde = 1,
                SectorHasta = 1
            };

            return View(model);
        }

        [CustomAuthorize(Actions = Aga.GestionDeArchivos.Services.Actions.ImprimirEtiquetasUbicaciones)]
        public ActionResult Imprimir(EtiquetasModel model)
        {
            EstanteriaService service = new EstanteriaService();

            if (ModelState.IsValid)
            {
                var estanterias = service.GetByNumber(model.EstanteriaId);

                estanterias = estanterias
                    .Where(e => 
                        e.Numero.Equals(model.EstanteriaId) && 
                        e.Sector >= model.SectorDesde && 
                        e.Sector <= model.SectorHasta);

                var newModel = new ImprimirModel
                {
                    Estanterias = estanterias.AsEnumerable()
                };

                return View(newModel);
            }
            else
            {
                List<int> estanterias = service.GetAllNumbers();

                List<SelectListItem> filtro = GetFilter(0,
                    estanterias.Select(e => e).Distinct(),
                    num => new SelectListItem { Text = num.ToString(), Value = num.ToString(), Selected = num.Equals(0) });

                model.Estanterias = filtro;

                return View(model);
            }
        }
    }
}
